Finding AIDS impact in r square

Finding information in data using statistical characteristics R-squared is a statistical measure of how close the data are to the fitted regression line

Inspired by

library(gapminder)
library(tidyverse)
tidyverse_packages()
 [1] "broom"     "dplyr"     "forcats"   "ggplot2"   "haven"     "httr"      "hms"       "jsonlite"  "lubridate" "magrittr"  "modelr"    "purrr"     "readr"    
[14] "readxl"    "stringr"   "tibble"    "rvest"     "tidyr"     "xml2"      "tidyverse"

Peek into data

summary(gapminder)
        country        continent        year         lifeExp           pop              gdpPercap       
 Afghanistan:  12   Africa  :624   Min.   :1952   Min.   :23.60   Min.   :6.001e+04   Min.   :   241.2  
 Albania    :  12   Americas:300   1st Qu.:1966   1st Qu.:48.20   1st Qu.:2.794e+06   1st Qu.:  1202.1  
 Algeria    :  12   Asia    :396   Median :1980   Median :60.71   Median :7.024e+06   Median :  3531.8  
 Angola     :  12   Europe  :360   Mean   :1980   Mean   :59.47   Mean   :2.960e+07   Mean   :  7215.3  
 Argentina  :  12   Oceania : 24   3rd Qu.:1993   3rd Qu.:70.85   3rd Qu.:1.959e+07   3rd Qu.:  9325.5  
 Australia  :  12                  Max.   :2007   Max.   :82.60   Max.   :1.319e+09   Max.   :113523.1  
 (Other)    :1632                                                                                       
gapminder %>% filter(gdpPercap < 300)
# Print xy plot -----------------------------------------------------------
gapminder <- gapminder %>% mutate(year1950 = year -1950)
ggplot(gapminder, aes(x=year, y=lifeExp)) +geom_line(aes(group = country))

Plot data

# Print xy plot -----------------------------------------------------------
gapminder <- gapminder %>% mutate(year1950 = year -1950)
ggplot(gapminder, aes(x=year, y=lifeExp)) +geom_line(aes(group = country))

Data wrangling

lets transform the data so that we keep all of a country’s data in one row

  • build nested data.frame
  • access elements of nested data.frame
# Nested data -------------------------------------------------------------
by_country <- gapminder  %>%
  group_by(continent, country) %>%
  nest()
by_country                  # show content of df
str(by_country[1:3,])       # show structure of first 3 rows of grouped and nested df
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   3 obs. of  3 variables:
 $ continent: Factor w/ 5 levels "Africa","Americas",..: 3 4 1
 $ country  : Factor w/ 142 levels "Afghanistan",..: 1 2 3
 $ data     :List of 3
  ..$ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame':    12 obs. of  5 variables:
  .. ..$ year     : int  1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 ...
  .. ..$ lifeExp  : num  28.8 30.3 32 34 36.1 ...
  .. ..$ pop      : int  8425333 9240934 10267083 11537966 13079460 14880372 12881816 13867957 16317921 22227415 ...
  .. ..$ gdpPercap: num  779 821 853 836 740 ...
  .. ..$ year1950 : num  2 7 12 17 22 27 32 37 42 47 ...
  ..$ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame':    12 obs. of  5 variables:
  .. ..$ year     : int  1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 ...
  .. ..$ lifeExp  : num  55.2 59.3 64.8 66.2 67.7 ...
  .. ..$ pop      : int  1282697 1476505 1728137 1984060 2263554 2509048 2780097 3075321 3326498 3428038 ...
  .. ..$ gdpPercap: num  1601 1942 2313 2760 3313 ...
  .. ..$ year1950 : num  2 7 12 17 22 27 32 37 42 47 ...
  ..$ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame':    12 obs. of  5 variables:
  .. ..$ year     : int  1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 ...
  .. ..$ lifeExp  : num  43.1 45.7 48.3 51.4 54.5 ...
  .. ..$ pop      : int  9279525 10270856 11000948 12760499 14760787 17152804 20033753 23254956 26298373 29072015 ...
  .. ..$ gdpPercap: num  2449 3014 2551 3247 4183 ...
  .. ..$ year1950 : num  2 7 12 17 22 27 32 37 42 47 ...
by_country$data[[1]]        # show data of first row
by_country$data[1]          # show data of first row
[[1]]
by_country$data[[1]][[2]]   # show  contents of second column 
 [1] 28.801 30.332 31.997 34.020 36.088 38.438 39.854 40.822 41.674 41.763 42.129 43.828
by_country$data[[1]][2]     # show second column
  • [ returns a list
  • [[ returns content of list

a good explanation can be found at: http://r4ds.had.co.nz/vectors.html#lists

Structure of dataframe

The column data is a list of data frames. Therefore, we have now a row per country and all data of that country in a dataframe in one column.

In a grouped dataframe each row is an oberservation, in a nested dataframe each row is a group, in this case, a group of a country’s observations.

Build a model

Lets build a model for each country, lifeExp ~ year

# Fit models --------------------------------------------------------------
country_model <- function(df){
  lm(lifeExp  ~  year1950, data=df)  # use year1950 because the absolute value is not important
}
models <- by_country %>%
  mutate(
    model = map(data, country_model)
  )
models
lm(lifeExp  ~  year1950, data=by_country$data[[1]]) 

Call:
lm(formula = lifeExp ~ year1950, data = by_country$data[[1]])

Coefficients:
(Intercept)     year1950  
    29.3566       0.2753  
models$model[1]
[[1]]

Call:
lm(formula = lifeExp ~ year1950, data = df)

Coefficients:
(Intercept)     year1950  
    29.3566       0.2753  

Combine data wrangling and model building

# Put it all together -----------------------------------------------------
by_country <- gapminder  %>%
  group_by(continent, country) %>%
  nest() %>%  
  mutate(
    model = map(data, country_model)
  )
by_country

Get the model data in a tidy form using the broom package

models <- models %>%
  mutate(
    glance  = map(model, broom::glance),        # Construct a single row summary "glance" of a model
    rsq     = glance %>% map_dbl("r.squared"),  # note the pipe within mutate(...)
    tidy    = map(model, broom::tidy),          # Tidy the result of a test into a summary data.frame
    augment = map(model, broom::augment)
  )
models
models$glance[1]
[[1]]
models$rsq[1]
[1] 0.9477123
models$tidy[1]
[[1]]
models$augment[1]
[[1]]
NA

Investigate how well the model fits

models %>% 
  ggplot(aes(rsq, country)) +
  geom_point(aes(colour = continent)) 

# source("gapminderShiny.R")

is the plot clear? how could it be improved?

ggplot orders categorical variables alphabetically

models %>% 
  ggplot(aes(rsq, reorder(country, rsq))) +
  geom_point(aes(colour = continent)) 

Find the countries with the worst fit

  models %>% filter((rsq<0.1 & rsq>0))  %>% unnest(rsq)  %>% top_n(6,rsq) %>% unnest(data) %>% 
    ggplot(aes(year, lifeExp)) +
    geom_line(aes( alpha = 1/3))  +
    facet_wrap(~country)

NA

How much did the countries improve life expectancy over time

# Unnest data -------------------------------------------------------------
unnest(models, data)
unnest(models, glance, .drop = TRUE) 
unnest(models, tidy)
# Plot data frame ---------------------------------------------------------
plotLife <- models %>%
  unnest(tidy) %>%
  select(continent, country, term, estimate, rsq) %>%
  spread(term, estimate) %>%
  ggplot(aes(`(Intercept)`,year1950))+
  geom_point(aes(colour = continent, size = rsq, fill = country)) +
  geom_smooth(se=FALSE) +
  xlab("Life expectancy (1950)") +
  ylab("Yearly improvement") +
  scale_size_area() + guides(fill=FALSE)
ggplotly(plotLife, tooltip = c("year1950", "country"))
`geom_smooth()` using method = 'loess'

where are the exeptions

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

LS0tCnRpdGxlOiAiR2FwbWluZGVyIGZvciBWSFMgMS8yMDE3IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiByZWFkYWJsZQogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgY3NzOiBzdHlsZS5jc3MKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQpodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKIyBGaW5kaW5nIEFJRFMgaW1wYWN0IGluIHIgc3F1YXJlCgpGaW5kaW5nIGluZm9ybWF0aW9uIGluIGRhdGEgdXNpbmcgc3RhdGlzdGljYWwgY2hhcmFjdGVyaXN0aWNzIAoqKlItc3F1YXJlZCoqIGlzIGEgc3RhdGlzdGljYWwgbWVhc3VyZSBvZiBob3cgY2xvc2UgdGhlIGRhdGEgYXJlIHRvIHRoZSBmaXR0ZWQgcmVncmVzc2lvbiBsaW5lCgoqKkluc3BpcmVkIGJ5ICoqCgotIFRFRCB0YWxrIG9mICAqKkhhbnMgUm9zbGluZyoqOiBMZXQgbXkgZGF0YXNldCBjaGFuZ2UgeW91ciBtaW5kc2V0Cmh0dHBzOi8vd3d3LnRlZC5jb20vdGFsa3MvaGFuc19yb3NsaW5nX2F0X3N0YXRlI3QtMTE3NjQwNwoKLSAqKkhhZGxleSBXaWNraGFtKiogTWFuYWdpbmcgbWFueSBtb2RlbHMgd2l0aCBSIGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9cnozX0ZEVnQ5ZWcgCgoKCgpgYGB7cn0KCmxpYnJhcnkoZ2FwbWluZGVyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKdGlkeXZlcnNlX3BhY2thZ2VzKCkKYGBgCgoKIyMgUGVlayBpbnRvIGRhdGEKCiAKYGBge3J9CnN1bW1hcnkoZ2FwbWluZGVyKQpnYXBtaW5kZXIgJT4lIGZpbHRlcihnZHBQZXJjYXAgPCAzMDApCgoKYGBgCgojIyMgUGxvdCBkYXRhCgpgYGB7cn0KIyBQcmludCB4eSBwbG90IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmdhcG1pbmRlciA8LSBnYXBtaW5kZXIgJT4lIG11dGF0ZSh5ZWFyMTk1MCA9IHllYXIgLTE5NTApCmdncGxvdChnYXBtaW5kZXIsIGFlcyh4PXllYXIsIHk9bGlmZUV4cCkpICtnZW9tX2xpbmUoYWVzKGdyb3VwID0gY291bnRyeSkpCmBgYAoKIyMjIERhdGEgd3JhbmdsaW5nCmxldHMgdHJhbnNmb3JtIHRoZSBkYXRhIHNvIHRoYXQgd2Uga2VlcCBhbGwgb2YgYSBjb3VudHJ5J3MgZGF0YSBpbiBvbmUgcm93CgotIGJ1aWxkIG5lc3RlZCBkYXRhLmZyYW1lCi0gYWNjZXNzIGVsZW1lbnRzIG9mIG5lc3RlZCBkYXRhLmZyYW1lCgpgYGB7cn0KCiMgTmVzdGVkIGRhdGEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKYnlfY291bnRyeSA8LSBnYXBtaW5kZXIgICU+JQogIGdyb3VwX2J5KGNvbnRpbmVudCwgY291bnRyeSkgJT4lCiAgbmVzdCgpCgpieV9jb3VudHJ5ICAgICAgICAgICAgICAgICAgIyBzaG93IGNvbnRlbnQgb2YgZGYKc3RyKGJ5X2NvdW50cnlbMTozLF0pICAgICAgICMgc2hvdyBzdHJ1Y3R1cmUgb2YgZmlyc3QgMyByb3dzIG9mIGdyb3VwZWQgYW5kIG5lc3RlZCBkZgpieV9jb3VudHJ5JGRhdGFbWzFdXSAgICAgICAgIyBzaG93IGRhdGEgb2YgZmlyc3Qgcm93CmJ5X2NvdW50cnkkZGF0YVsxXSAgICAgICAgICAjIHNob3cgZGF0YSBvZiBmaXJzdCByb3cKYnlfY291bnRyeSRkYXRhW1sxXV1bWzJdXSAgICMgc2hvdyAgY29udGVudHMgb2Ygc2Vjb25kIGNvbHVtbiAKYnlfY291bnRyeSRkYXRhW1sxXV1bMl0gICAgICMgc2hvdyBzZWNvbmQgY29sdW1uCmBgYAoKCi0gWyByZXR1cm5zIGEgbGlzdAotIFtbIHJldHVybnMgY29udGVudCBvZiBsaXN0CgphIGdvb2QgZXhwbGFuYXRpb24gY2FuIGJlIGZvdW5kIGF0OiBodHRwOi8vcjRkcy5oYWQuY28ubnovdmVjdG9ycy5odG1sI2xpc3RzIAoKIyMjIFN0cnVjdHVyZSBvZiBkYXRhZnJhbWUKClRoZSBjb2x1bW4gKipkYXRhKiogaXMgYSBsaXN0IG9mIGRhdGEgZnJhbWVzLiBUaGVyZWZvcmUsIHdlIGhhdmUgbm93IGEgcm93IHBlciBjb3VudHJ5IGFuZCBhbGwgZGF0YSBvZiB0aGF0IGNvdW50cnkgaW4gYSBkYXRhZnJhbWUgaW4gKipvbmUqKiBjb2x1bW4uCgpJbiBhIGdyb3VwZWQgZGF0YWZyYW1lICoqZWFjaCByb3cgaXMgYW4gb2JlcnNlcnZhdGlvbioqLCBpbiBhIG5lc3RlZCBkYXRhZnJhbWUgKiplYWNoIHJvdyBpcyBhIGdyb3VwKiosIGluIHRoaXMgY2FzZSwgYSBncm91cCBvZiBhIGNvdW50cnnigJlzIG9ic2VydmF0aW9ucy4KCgoKIyMgQnVpbGQgYSBtb2RlbApMZXRzIGJ1aWxkIGEgbW9kZWwgZm9yIGVhY2ggY291bnRyeSwgbGlmZUV4cCB+ICB5ZWFyCgoKYGBge3J9CgojIEZpdCBtb2RlbHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmNvdW50cnlfbW9kZWwgPC0gZnVuY3Rpb24oZGYpewogIGxtKGxpZmVFeHAgIH4gIHllYXIxOTUwLCBkYXRhPWRmKSAgIyB1c2UgeWVhcjE5NTAgYmVjYXVzZSB0aGUgYWJzb2x1dGUgdmFsdWUgaXMgbm90IGltcG9ydGFudAp9Cm1vZGVscyA8LSBieV9jb3VudHJ5ICU+JQogIG11dGF0ZSgKICAgIG1vZGVsID0gbWFwKGRhdGEsIGNvdW50cnlfbW9kZWwpCiAgKQptb2RlbHMKbG0obGlmZUV4cCAgfiAgeWVhcjE5NTAsIGRhdGE9YnlfY291bnRyeSRkYXRhW1sxXV0pIAptb2RlbHMkbW9kZWxbMV0KCmBgYAoKIyMjIENvbWJpbmUgZGF0YSB3cmFuZ2xpbmcgYW5kIG1vZGVsIGJ1aWxkaW5nCgpgYGB7cn0KCiMgUHV0IGl0IGFsbCB0b2dldGhlciAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKYnlfY291bnRyeSA8LSBnYXBtaW5kZXIgICU+JQogIGdyb3VwX2J5KGNvbnRpbmVudCwgY291bnRyeSkgJT4lCiAgbmVzdCgpICU+JSAgCiAgbXV0YXRlKAogICAgbW9kZWwgPSBtYXAoZGF0YSwgY291bnRyeV9tb2RlbCkKICApCgpieV9jb3VudHJ5CmBgYAoKCgojIyBHZXQgdGhlIG1vZGVsIGRhdGEgaW4gYSB0aWR5IGZvcm0gdXNpbmcgdGhlICoqYnJvb20qKiBwYWNrYWdlCgpgYGB7cn0KbW9kZWxzIDwtIG1vZGVscyAlPiUKICBtdXRhdGUoCiAgICBnbGFuY2UgID0gbWFwKG1vZGVsLCBicm9vbTo6Z2xhbmNlKSwgICAgICAgICMgQ29uc3RydWN0IGEgc2luZ2xlIHJvdyBzdW1tYXJ5ICJnbGFuY2UiIG9mIGEgbW9kZWwKICAgIHJzcSAgICAgPSBnbGFuY2UgJT4lIG1hcF9kYmwoInIuc3F1YXJlZCIpLCAgIyBub3RlIHRoZSBwaXBlIHdpdGhpbiBtdXRhdGUoLi4uKQogICAgdGlkeSAgICA9IG1hcChtb2RlbCwgYnJvb206OnRpZHkpLCAgICAgICAgICAjIFRpZHkgdGhlIHJlc3VsdCBvZiBhIHRlc3QgaW50byBhIHN1bW1hcnkgZGF0YS5mcmFtZQogICAgYXVnbWVudCA9IG1hcChtb2RlbCwgYnJvb206OmF1Z21lbnQpICAgICAgICAjIGFkZCBjb2x1bW5zIHRvIHRoZSBvcmlnaW5hbCBkYXRhc2V0IHN1Y2ggYXMgcHJlZGljdGlvbnMsIHJlc2lkdWFscyBhbmQgY2x1c3RlciBhc3NpZ25tZW50cwogICkgCm1vZGVscwptb2RlbHMkZ2xhbmNlWzFdCm1vZGVscyRyc3FbMV0KbW9kZWxzJHRpZHlbMV0KbW9kZWxzJGF1Z21lbnRbMV0KYGBgCgojIyMgSW52ZXN0aWdhdGUgaG93IHdlbGwgdGhlIG1vZGVsIGZpdHMgCgoKYGBge3J9Cgptb2RlbHMgJT4lIAogIGdncGxvdChhZXMocnNxLCBjb3VudHJ5KSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IGNvbnRpbmVudCkpIAojIHNvdXJjZSgiZ2FwbWluZGVyU2hpbnkuUiIpCmBgYAoKaXMgdGhlIHBsb3QgY2xlYXI/IGhvdyBjb3VsZCBpdCBiZSBpbXByb3ZlZD8KCgoKZ2dwbG90IG9yZGVycyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYWxwaGFiZXRpY2FsbHkgCgpgYGB7cn0KCm1vZGVscyAlPiUgCiAgZ2dwbG90KGFlcyhyc3EsIHJlb3JkZXIoY291bnRyeSwgcnNxKSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBjb250aW5lbnQpKSAKCmBgYAoKIyMjIEZpbmQgdGhlIGNvdW50cmllcyB3aXRoIHRoZSB3b3JzdCBmaXQKCgpgYGB7cn0KCiAgbW9kZWxzICU+JSBmaWx0ZXIoKHJzcTwwLjEgJiByc3E+MCkpICAlPiUgdW5uZXN0KHJzcSkgICU+JSB0b3Bfbig2LHJzcSkgJT4lIHVubmVzdChkYXRhKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHllYXIsIGxpZmVFeHApKSArCiAgICBnZW9tX2xpbmUoYWVzKCBhbHBoYSA9IDEvMykpICArCiAgICBmYWNldF93cmFwKH5jb3VudHJ5KQogIApgYGAKCiMgSG93IG11Y2ggZGlkIHRoZSBjb3VudHJpZXMgaW1wcm92ZSBsaWZlIGV4cGVjdGFuY3kgb3ZlciB0aW1lCgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkocGxvdGx5KQojIFVubmVzdCBkYXRhIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCnVubmVzdChtb2RlbHMsIGRhdGEpCnVubmVzdChtb2RlbHMsIGdsYW5jZSwgLmRyb3AgPSBUUlVFKSAKdW5uZXN0KG1vZGVscywgdGlkeSkKCiMgUGxvdCBkYXRhIGZyYW1lIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCnBsb3RMaWZlIDwtIG1vZGVscyAlPiUKICB1bm5lc3QodGlkeSkgJT4lCiAgc2VsZWN0KGNvbnRpbmVudCwgY291bnRyeSwgdGVybSwgZXN0aW1hdGUsIHJzcSkgJT4lCiAgc3ByZWFkKHRlcm0sIGVzdGltYXRlKSAlPiUKICBnZ3Bsb3QoYWVzKGAoSW50ZXJjZXB0KWAseWVhcjE5NTApKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBjb250aW5lbnQsIHNpemUgPSByc3EsIGZpbGwgPSBjb3VudHJ5KSkgKwogIGdlb21fc21vb3RoKHNlPUZBTFNFKSArCiAgeGxhYigiTGlmZSBleHBlY3RhbmN5ICgxOTUwKSIpICsKICB5bGFiKCJZZWFybHkgaW1wcm92ZW1lbnQiKSArCiAgc2NhbGVfc2l6ZV9hcmVhKCkgKyBndWlkZXMoZmlsbD1GQUxTRSkKZ2dwbG90bHkocGxvdExpZmUsIHRvb2x0aXAgPSBjKCJ5ZWFyMTk1MCIsICJjb3VudHJ5IikpCgoKCmBgYAojIyB3aGVyZSBhcmUgdGhlIGV4ZXB0aW9ucwoKYGBge3J9Cgp1bm5lc3QobW9kZWxzLCBhdWdtZW50KSAjIHVzaW5nIHRoZSB1bm5lc3Qgd2l0aCBvbmUgYXVnbWVudCBhcmd1bWVudCBrZWVwcyB0aGUgZ3JvdXBpbmcgdmFyaWFibGVzIGFuZCBhdWdtZW50IAoKbW9kZWxzICU+JSB1bm5lc3QoYXVnbWVudCkgJT4lIAogIGdncGxvdChhZXMoeWVhcjE5NTAsIC5yZXNpZCkpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gY291bnRyeSksIGFscGhhID0gMS8zKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG91ciA9ICJ3aGl0ZSIpICsKICBmYWNldF93cmFwKH5jb250aW5lbnQsIHNjYWxlcyA9ICJmcmVlX3kiKSAKCgpgYGAKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDbWQrT3B0aW9uK0kqLgoKV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDbWQrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4=